#ifndef _INCLUDED_CLASS_WORK_THREAD_H_
#define _INCLUDED_CLASS_WORK_THREAD_H_
//=======================================================================//
//= Include files.													    =//
//=======================================================================//
#include <wx/string.h>
#include <wx/window.h>
#include <wx/thread.h>
#include "Encoder.h"
//=======================================================================//
//= Marco declare.                                                      =//
//=======================================================================//
#define EVT_WORK_START(ID, FUNC) \
    DECLARE_EVENT_TABLE_ENTRY(wxEVT_WORK_START, ID, -1, (wxObjectEventFunction)(wxEventFunction)(WorkStartFunc)&FUNC, (wxObject*)NULL),
#define EVT_WORK_END(ID, FUNC) \
    DECLARE_EVENT_TABLE_ENTRY(wxEVT_WORK_END, ID, -1, (wxObjectEventFunction)(wxEventFunction)(WorkStopFunc)&FUNC, (wxObject*)NULL),
#define EVT_TEXT_CONV(ID, FUNC) \
    DECLARE_EVENT_TABLE_ENTRY(wxEVT_TEXT_CONV, ID, -1, (wxObjectEventFunction)(wxEventFunction)(TextConvFunc)&FUNC, (wxObject*)NULL),
#define EVT_IMAGE_CONV(ID, FUNC) \
    DECLARE_EVENT_TABLE_ENTRY(wxEVT_IMAGE_CONV, ID, -1, (wxObjectEventFunction)(wxEventFunction)(ImageConvFonc)&FUNC, (wxObject*)NULL),

//=======================================================================//
//= Data type declare.                                                  =//
//=======================================================================//
class WorkThreadBase;
class WorkStartEvent;
class WorkEndEvent;
class TextConvEvent;
class ImageConvEvent;
DECLARE_LOCAL_EVENT_TYPE(wxEVT_WORK_START,	evtID_WORK_START);
DECLARE_LOCAL_EVENT_TYPE(wxEVT_WORK_END,	evtID_WORK_END);
DECLARE_LOCAL_EVENT_TYPE(wxEVT_TEXT_CONV,	evtID_TEXT_CONV);
DECLARE_LOCAL_EVENT_TYPE(wxEVT_IMAGE_CONV,	evtID_IMAGE_CONV)
typedef void (wxEvtHandler::*WorkStartFunc)(WorkStartEvent&);
typedef void (wxEvtHandler::*WorkStopFunc)(WorkEndEvent&);
typedef void (wxEvtHandler::*TextConvFunc)(TextConvEvent&);
typedef void (wxEvtHandler::*ImageConvFonc)(ImageConvEvent&);

//=======================================================================//
//= Global variable declare.										    =//
//=======================================================================//

//=======================================================================//
//= Class declare.                                                      =//
//=======================================================================//
class WorkStartEvent: public wxEvent
{
	DECLARE_DYNAMIC_CLASS(WorkStartEvent)
private:
    int							m_iTotal;

public:
								WorkStartEvent(int iID = wxID_ANY);
								WorkStartEvent(const WorkStartEvent& clsEvent);
    virtual WorkStartEvent*		Clone(void) const					{return new WorkStartEvent(*this);}
    int							GetTotal(void) const				{return m_iTotal;}
    void						SetTotal(int iTotal)				{m_iTotal = iTotal;}
};

class WorkEndEvent: public wxEvent
{
	DECLARE_DYNAMIC_CLASS(WorkEndEvent)
public:
								WorkEndEvent(int iID = wxID_ANY);
								WorkEndEvent(const WorkStartEvent& clsEvent);
    virtual WorkEndEvent*		Clone(void) const					{return new WorkEndEvent(*this);}
};

class TextConvEvent: public wxEvent
{
    DECLARE_DYNAMIC_CLASS(TextConvEvent)

private:
    int							m_iTotal;
	int							m_iProcessed;
	RasterizedMonoChar			m_clsMonoCharData;
public:
								TextConvEvent(int iID = wxID_ANY);
								TextConvEvent(const TextConvEvent& clsSource);
    virtual TextConvEvent*		Clone(void) const					{return new TextConvEvent(*this);}
	int							GetTotal(void) const				{return m_iTotal;}
	int							GetProcessed(void) const			{return m_iProcessed;}
	void						SetTotal(int iTotal)				{m_iTotal = iTotal;}
	void						SetProcessed(int iProcessed)		{m_iProcessed = iProcessed;}
	const RasterizedMonoChar&			GetData(void) const					{return m_clsMonoCharData;}
	void						SetData(const RasterizedMonoChar& clsData){m_clsMonoCharData = clsData;}
};

class ImageConvEvent: public wxEvent
{
    DECLARE_DYNAMIC_CLASS(ImageConvEvent)
private:
	RasterizedMonoImage			m_clsMonoImageData;

public:
								ImageConvEvent(int iID = wxID_ANY);
								ImageConvEvent(const ImageConvEvent& clsSource);
    virtual ImageConvEvent*		Clone(void) const					{return new ImageConvEvent(*this);}
	const RasterizedMonoImage&	GetData(void) const					{return m_clsMonoImageData;}
	void						SetData(const RasterizedMonoImage& clsData){m_clsMonoImageData = clsData;}
};

class WorkThreadMgr
{
	wxDECLARE_NO_COPY_CLASS(WorkThreadMgr);
private:
	wxEvtHandler*				m_pclsEvtHandler;
	WorkThreadBase*				m_pclsThread;
	wxCriticalSection			m_clsCriticalSection;
	int							m_iID;

	static WorkThreadMgr&		_getInstance(void);
								WorkThreadMgr(void);
public:
	static WorkThreadMgr&		Instance(void);
	static WorkThreadMgr&		Instance(int iID);
								~WorkThreadMgr(void);
	bool						StartThread(wxEvtHandler* pclsEvtHandle, WorkThreadBase* pclsThread);
	bool						StopThread(void);
	void						OnThreadStop(void);
	void						PostEvent(const wxEvent& clsEvent);
	WorkThreadMgr&				SetID(int iNewID)						{m_iID = iNewID; return *this;}
	int							GetID(void) const 						{return m_iID;}
	bool						IsRunning(void);
};

class WorkThreadBase
: public wxThread
{
	wxDECLARE_NO_COPY_CLASS(WorkThreadBase);
private:
	WorkThreadMgr*				m_pclsOwner;

protected:
	void						PostEvent(wxEvent& clsEvent);
	const WorkThreadMgr*		Owner(void)	const						{return m_pclsOwner;}
	virtual void				OnThreadStart(int iTotal) = 0;

public:
								WorkThreadBase(void);
								~WorkThreadBase(void);
	void						SetOwner(WorkThreadMgr& clsOwner);
};

class TextWorkThread
: public WorkThreadBase
{
	wxDECLARE_NO_COPY_CLASS(TextWorkThread);
private:
	wxString					m_strTextResource;
								TextWorkThread(const wxString& strText);
protected:
	wxThread::ExitCode			Entry(void);
	virtual void				OnThreadStart(int iTotal = 0);

public:

								~TextWorkThread(void);
	static TextWorkThread*		New(const wxString& strText);
};

class ImageWorkThread
: public WorkThreadBase
{
	wxDECLARE_NO_COPY_CLASS(ImageWorkThread);
private:
	wxImage						m_clsImageResource;
								ImageWorkThread(const wxImage& clsImage);
protected:
	wxThread::ExitCode			Entry(void);
	virtual void				OnThreadStart(int iTotal = 0);

public:

								~ImageWorkThread(void);
	static ImageWorkThread*		New(const wxImage& clsImage);
};


#endif // _INCLUDED_CLASS_WORK_THREAD_H_
